package com.cloud.point.concurrent.threadPool;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

import lombok.extern.slf4j.Slf4j;

/**
 * TestFork-Join
 *
 * @author H
 * @version 1.0
 * @date 2024-05-24 10:38
 */
@Slf4j
public class TestForkJoin {

    public static void main(String[] args) {
        ForkJoinPool pool = new ForkJoinPool(5);
        Integer res = pool.invoke(new TestTask(5));
        log.info("{}", res);
        Integer res2 = pool.invoke(new TestMultiTask(1, 10));
        log.info("{}", res2);

    }

    static class TestMultiTask extends RecursiveTask<Integer> {
        private int begin;
        private int end;

        public TestMultiTask(int begin, int end) {
            this.begin = begin;
            this.end = end;
        }

        @Override
        protected Integer compute() {
            if (begin == end) {
                return begin;
            }
            // 减少一次拆分；相邻两数再拆也是自身值
            if (end - begin == 1) {
                return begin + end;
            }
            int mid = (begin + end) / 2;
            /**
             * 多次拆分；拆分两次任务
             */

            TestMultiTask task1 = new TestMultiTask(begin, mid);
            TestMultiTask task2 = new TestMultiTask(mid + 1, end);

            task1.fork();
            task2.fork();
            log.info("fork:{},{}|{},{}", begin, end, task1, task2);

            Integer result = task1.join() + task2.join();
            log.info("join:{},{}|{},{}", begin, end, task1, task2);
            return result;
        }

        @Override
        public String toString() {
            return "task{" +
                    begin + "," + end +
                    '}';
        }
    }

    static class TestTask extends RecursiveTask<Integer> {

        private int count;

        public TestTask(int count) {
            this.count = count;
        }

        @Override
        protected Integer compute() {
            if (count == 1) {
                log.info("count:{}", count);
                return count;
            }
            /**
             * 每次只拆分单个任务；效率较低；
             */
            TestTask nextTask = new TestTask(count - 1);
            // 开启子任务线程
            nextTask.fork();
            log.info("fork:{},{}", count, nextTask);

            //获取子线程执行结果
            Integer result = count + nextTask.join();
            log.info("join:{},{}", count, nextTask);
            return result;
        }

        @Override
        public String toString() {
            return "task{" +
                    count +
                    '}';
        }
    }

}

